package client;

import javax.swing.JFrame;
import javax.swing.JPanel;

import model.channel.Channel;
import model.invocatedMethods.SensorModifierRunnable;

import commands.ActivateSensorModifierCommand;
import commands.AllowChangesOnApplicationPanelCommandImpl;
import commands.BlockChangesOnApplicationPanelCommandImpl;
import commands.DesactivateSensorModifierCommand;
import commands.NotifyChangesToApplicationPanelCommandImpl;
import commands.NotifyChangesToDisplayerPanelCommandImpl;
import commands.NotifyChangesToSensorCommandImpl;
import commands.NotifyStrategyChangesToSensorCommandImpl;
import constants.Constants;
import factory.CentralFactory;
import factory.CentralFactoryImpl;
import factory.ExecutorFactory;

import ihm.ApplicationPanel;
import ihm.ApplicationPanelImpl;
import ihm.DisplayerPanel;
import ihm.SensorModifierActivationPanel;
import ihm.SensorModifierActivationPanelImpl;
import model.observer.SensorObserver;
import model.subject.*;

/**
 * Classe cliente de l'application. 
 */
public class Client {

	public static void main(String[] args) {
		// Création du sujet
		CentralFactory factory = new CentralFactoryImpl();
		
		Sensor sensor = factory.createSensor();
		sensor.setSpreadingAlgorithme(factory.createSpreadingAlgorithme(Constants.STRATEGY_DEFAULT));

		// Création des observeurs
		SensorObserver displayer1 = factory.createSensorObserver();
		
		SensorObserver displayer2 = factory.createSensorObserver();
		
		SensorObserver displayer3 = factory.createSensorObserver();
		
		// Création des canaux
		Channel channel1 = factory.createChannel();
		channel1.setLatency(0);
		
		Channel channel2 = factory.createChannel();
		channel2.setLatency(1000);
		
		Channel channel3 = factory.createChannel();
		channel3.setLatency(300);
		
		// Injection des dépendances
		sensor.attach(channel1);
		sensor.attach(channel2);
		sensor.attach(channel3);
	
		channel1.setSensor(sensor);
		channel1.setSensorObserver(displayer1);
		
		channel2.setSensor(sensor);
		channel2.setSensorObserver(displayer2);
		
		channel3.setSensor(sensor);
		channel3.setSensorObserver(displayer3);
		
		// Création de l'IHM
		DisplayerPanel displayerPanel1 = factory.createDisplayerPanel();
		DisplayerPanel displayerPanel2 = factory.createDisplayerPanel();
		DisplayerPanel displayerPanel3 = factory.createDisplayerPanel();

		displayer1.setNotifyChangesToDisplayerPanelCommand(new NotifyChangesToDisplayerPanelCommandImpl(displayer1, displayerPanel1));
		displayer2.setNotifyChangesToDisplayerPanelCommand(new NotifyChangesToDisplayerPanelCommandImpl(displayer2, displayerPanel2));
		displayer3.setNotifyChangesToDisplayerPanelCommand(new NotifyChangesToDisplayerPanelCommandImpl(displayer3, displayerPanel3));

		SensorModifierRunnable SensorModifierRunnable = new model.invocatedMethods.SensorModifierRunnable(sensor);
		SensorModifierActivationPanel sensorModifierActivationPanel = new SensorModifierActivationPanelImpl();
		sensorModifierActivationPanel.setActivateSensorModifierCommand(new ActivateSensorModifierCommand(SensorModifierRunnable));
		sensorModifierActivationPanel.setDesactivateSensorModifierCommand(new DesactivateSensorModifierCommand(SensorModifierRunnable));
		
		ApplicationPanel applicationPanel = new ApplicationPanelImpl();
		sensor.setNotifyChangesToApplicationPanelCommand(new NotifyChangesToApplicationPanelCommandImpl(applicationPanel, sensor));
		((Lockable)sensor).setAllowChangesOnApplicationPanelCommand(new AllowChangesOnApplicationPanelCommandImpl(applicationPanel));
		((Lockable)sensor).setBlockChangesOnApplicationPanelCommand(new BlockChangesOnApplicationPanelCommandImpl(applicationPanel));
		applicationPanel.setNotifyChangesToSensorCommand(new NotifyChangesToSensorCommandImpl(applicationPanel, sensor));
		applicationPanel.setNotifyStrategyChangesToSensorCommand(new NotifyStrategyChangesToSensorCommandImpl(applicationPanel, sensor, factory));
		applicationPanel.addDisplayerPanel(displayerPanel1);
		applicationPanel.addDisplayerPanel(displayerPanel2);
		applicationPanel.addDisplayerPanel(displayerPanel3);
		applicationPanel.addSensorModifierActivationPanel(sensorModifierActivationPanel);
		
		JFrame asynchronousObservers = new JFrame("Asynchronous Observers");
		asynchronousObservers.getContentPane().add((JPanel)applicationPanel);
		asynchronousObservers.setBounds(10, 10, 600, 300);
		asynchronousObservers.setVisible(true);
		asynchronousObservers.setResizable(false);
		asynchronousObservers.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		// Lancement de la modification automatique du capteur
		ExecutorFactory.getInstance().execute(SensorModifierRunnable);
	}
	
}
